#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>

void run_shell() {
    char command[1024];

    while (1) {
        char cwd[1024];
        if (getcwd(cwd, sizeof(cwd)) != NULL)
            printf("[%s] myshell> ", cwd);
        else
            perror("getcwd failed");

        if (fgets(command, sizeof(command), stdin) == NULL)
            continue;
        if (command[strlen(command) - 1] == '\n')
            command[strlen(command) - 1] = '\0';
        if (strcmp(command, "exit") == 0)
            break;

        // 保留命令副本用于提取重定向信息
        char raw_command[1024];
        strcpy(raw_command, command);

        // --- 提取重定向信息 ---
        char input_file[128] = {0};
        char output_file[128] = {0};
        int append_mode = 0;

        char *input_pos = strchr(raw_command, '<');
        char *output_pos = strstr(raw_command, ">>");
        if (output_pos) append_mode = 1;
        else output_pos = strchr(raw_command, '>');

        if (input_pos) {
            char *tmp = input_pos + 1;
            while (*tmp == ' ') tmp++;
            sscanf(tmp, "%127s", input_file);
        }

        if (output_pos) {
            char *tmp = output_pos + (append_mode ? 2 : 1);
            while (*tmp == ' ') tmp++;
            sscanf(tmp, "%127s", output_file);
        }

        // 使用原命令行继续拆分管道（不剪断内容）
        // --- 拆分管道 ---
        char *cmds[10];
        int cmd_count = 0;
        char *token = strtok(command, "|");
        while (token && cmd_count < 10) {
            while (*token == ' ') token++; // 去前导空格
            cmds[cmd_count++] = token;
            token = strtok(NULL, "|");
        }

        int prev_fd = -1;
        int pipefd[2];

        for (int i = 0; i < cmd_count; ++i) {
            if (i < cmd_count - 1 && pipe(pipefd) < 0) {
                perror("pipe failed");
                exit(1);
            }

            pid_t pid = fork();
            if (pid == 0) {
                // 子进程
                if (prev_fd != -1) {
                    dup2(prev_fd, STDIN_FILENO);
                    close(prev_fd);
                }
                if (i < cmd_count - 1) {
                    close(pipefd[0]);
                    dup2(pipefd[1], STDOUT_FILENO);
                    close(pipefd[1]);
                }

                // --- 重定向 ---
                if (i == 0 && input_file[0] != '\0') {
                    int fd = open(input_file, O_RDONLY);
                    if (fd < 0) {
                        perror("open input failed");
                        exit(1);
                    }
                    dup2(fd, STDIN_FILENO);
                    close(fd);
                }
                if (i == cmd_count - 1 && output_file[0] != '\0') {
                    int flags = O_WRONLY | O_CREAT | (append_mode ? O_APPEND : O_TRUNC);
                    int fd = open(output_file, flags, 0644);
                    if (fd < 0) {
                        perror("open output failed");
                        exit(1);
                    }
                    dup2(fd, STDOUT_FILENO);
                    close(fd);
                }

                // --- 拆分参数 ---
                char *args[64];
                int j = 0;
                char *arg = strtok(cmds[i], " ");
                while (arg) {
                    if (strcmp(arg, "<") == 0 || strcmp(arg, ">") == 0 || strcmp(arg, ">>") == 0)
                        break;
                    args[j++] = arg;
                    arg = strtok(NULL, " ");
                }
                args[j] = NULL;

                // 特殊内建命令 cd
                if (args[0] && strcmp(args[0], "cd") == 0) {
                    if (args[1] == NULL) {
                        fprintf(stderr, "cd: missing operand\n");
                    } else if (chdir(args[1]) != 0) {
                        perror("cd failed");
                    }
                    exit(0);
                }

                execvp(args[0], args);
                perror("exec failed");
                exit(1);
            }

            // 父进程
            if (prev_fd != -1) close(prev_fd);
            if (i < cmd_count - 1) {
                close(pipefd[1]);
                prev_fd = pipefd[0];
            }
        }

        for (int i = 0; i < cmd_count; ++i) wait(NULL);
    }
}

